<script setup lang="ts">
import * as THREE from "three";
import { ref, onMounted } from "vue";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import gsap from "gsap";
import * as dat from "dat.gui";

// 初始化场景
const scene = new THREE.Scene();

// 创建相机
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

// 设置相机位置
// camera.position.z = 30;

// 相机放入到场景中
camera.position.set(0, 0, 0.01);

const useBox = () => {
  const materials: THREE.MeshBasicMaterial[] = [];

  const texture_right = new THREE.TextureLoader().load(
    "./images/livingRoom/living_r.jpg"
  );
  materials.push(new THREE.MeshBasicMaterial({ map: texture_right }));

  const texture_left = new THREE.TextureLoader().load(
    "./images/livingRoom/living_l.jpg"
  );
  materials.push(new THREE.MeshBasicMaterial({ map: texture_left }));

  const texture_up = new THREE.TextureLoader().load(
    "./images/livingRoom/living_u.jpg"
  );
  materials.push(new THREE.MeshBasicMaterial({ map: texture_up }));

  const texture_down = new THREE.TextureLoader().load(
    "./images/livingRoom/living_d.jpg"
  );
  materials.push(new THREE.MeshBasicMaterial({ map: texture_down }));

  const texture_front = new THREE.TextureLoader().load(
    "./images/livingRoom/living_f.jpg"
  );
  materials.push(new THREE.MeshBasicMaterial({ map: texture_front }));

  const texture_back = new THREE.TextureLoader().load(
    "./images/livingRoom/living_b.jpg"
  );
  materials.push(new THREE.MeshBasicMaterial({ map: texture_back }));

  // 创建几何体
  const geometry = new THREE.BoxGeometry(10, 10, 10);
  // 创建材质
  // const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  // 创建网格
  const box = new THREE.Mesh(geometry, materials);
  box.geometry.scale(1, 1, -1);
  // 将网格添加到场景中
  scene.add(box);
};

const useSphere = () => {
  const sphereGeometry = new THREE.SphereGeometry(1, 50, 50);
  sphereGeometry.scale(1, 1, -1);
  const texture = new THREE.TextureLoader().load("./images/scene.jpeg");
  const sphereMaterial = new THREE.MeshBasicMaterial({ map: texture });

  const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
  scene.add(sphere);
};

// useBox();
// useSphere();

window.addEventListener("resize", () => {
  // 更新相机的宽高比
  camera.aspect = window.innerWidth / window.innerHeight;
  // 更新相机的投影矩阵
  camera.updateProjectionMatrix();
  // 更新渲染器的大小
  renderer.setSize(window.innerWidth, window.innerHeight);
});

const materials: THREE.MeshBasicMaterial[] = [];

const texture_right = new THREE.TextureLoader().load(
  "./images/livingRoom/living_r.jpg"
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_right }));

const texture_left = new THREE.TextureLoader().load(
  "./images/livingRoom/living_l.jpg"
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_left }));

const texture_up = new THREE.TextureLoader().load(
  "./images/livingRoom/living_u.jpg"
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_up }));

const texture_down = new THREE.TextureLoader().load(
  "./images/livingRoom/living_d.jpg"
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_down }));

const texture_front = new THREE.TextureLoader().load(
  "./images/livingRoom/living_f.jpg"
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_front }));

const texture_back = new THREE.TextureLoader().load(
  "./images/livingRoom/living_b.jpg"
);
materials.push(new THREE.MeshBasicMaterial({ map: texture_back }));

// 客厅立方体
// 创建几何体
const geometry = new THREE.BoxGeometry(10, 10, 10);
// const v3 = new THREE.Vector3(0, 0, 0);
// const e3 = new THREE.Euler(0, 10, 0);
// 创建材质
// const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 创建网格
const box = new THREE.Mesh(geometry, materials);
box.geometry.scale(1, 1, -1);

// box.position.x = 10;
// box.position.y = 10;
// box.position.set(10, 10, 0);
// box.position.copy(v3);
// box.rotation.copy(e3);
// 将网格添加到场景中
scene.add(box);

// 阳台立方体
const roomPrefix = "balcony";
const arr = [
  `${roomPrefix}_r`,
  `${roomPrefix}_l`,
  `${roomPrefix}_u`,
  `${roomPrefix}_d`,
  `${roomPrefix}_f`,
  `${roomPrefix}_b`,
];
const balconyMaterials: THREE.MeshBasicMaterial[] = [];
arr.forEach((item) => {
  const texture = new THREE.TextureLoader().load(
    `./images/balcony/${item}.jpg`
  );
  balconyMaterials.push(new THREE.MeshBasicMaterial({ map: texture }));
});

const balconyGeometry = new THREE.BoxGeometry(10, 10, 10);
const balconyV3 = new THREE.Vector3(0, 0, -10);
const balconyE3 = new THREE.Euler(0, 0, 0);
const balconyBox = new THREE.Mesh(balconyGeometry, balconyMaterials);
balconyBox.geometry.scale(1, 1, -1);
balconyBox.position.copy(balconyV3);
balconyBox.rotation.copy(balconyE3);
scene.add(balconyBox);

// gsap.to(box.position, { x: 5, duration: 2 });
// gsap.to(box.position, { y: 5, duration: 1 });
// gsap.to(box.rotation, { z: 5, duration: 2 });

// 定义阳台导航的canvas
const canvas = document.createElement("canvas");
canvas.width = 1024;
canvas.height = 1024;
const context = canvas.getContext("2d")!;
context.fillStyle = "rgba(100,100,100,.7)";
context.fillRect(0, 256, canvas.width, canvas.height / 2);
context.textAlign = "center";
context.textBaseline = "middle";
context.font = "bold 200px Arial";
context.fillStyle = "white";
context.fillText("阳台", canvas.width / 2, canvas.height / 2);

const balconySpriteTexture = new THREE.CanvasTexture(canvas);

// 创建阳台导航

const balconySpriteMaterial = new THREE.SpriteMaterial({
  map: balconySpriteTexture,
  transparent: true,
});

const balconySprite = new THREE.Sprite(balconySpriteMaterial);
const balconySpritePosition = new THREE.Vector3(0, 0, -4);
balconySprite.position.copy(balconySpritePosition);
scene.add(balconySprite);

const poiObjects: THREE.Sprite[] = [];
poiObjects.push(balconySprite);

const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();

// 添加点击事件
window.addEventListener("click", (event: MouseEvent) => {
  event.preventDefault();
  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
  pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
  pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;

  // 通过摄像机和鼠标位置更新射线
  raycaster.setFromCamera(pointer, camera);
  // 计算物体和射线的交点
  const intersects = raycaster.intersectObjects(poiObjects);
  if (intersects.length > 0) { 
    gsap.to(camera.position, {
      duration: 1,
      x: 0,
      y: 0,
      z: -10,
    });
  }
});

// 图形化控制界面
const gui = new dat.GUI();
// gui.add(box.position, 'x').name('移动x轴').min(-5).max(5).step(0.1);
// gui.add(box.position, 'y').name('移动y轴').min(-5).max(5).step(0.1);
// gui.add(box.position, 'z').name('移动z轴').min(-5).max(5).step(0.1);
// gui.addColor({ color: 0x00ff00 }, 'color').name('修改颜色').onChange((e) => {
//   box.material.color = new THREE.Color(e);
// })

const boxFolder = gui.addFolder("立方体属性");
boxFolder.add(box.position, "x").name("移动x轴").min(-5).max(5).step(0.1);
boxFolder.add(box.position, "y").name("移动y轴").min(-5).max(5).step(0.1);
boxFolder.add(box.position, "z").name("移动z轴").min(-5).max(5).step(0.1);
boxFolder.add(box.rotation, "x").name("旋转x轴").min(-5).max(5).step(0.1);
boxFolder.add(box.rotation, "y").name("旋转y轴").min(-5).max(5).step(0.1);
boxFolder.add(box.rotation, "z").name("旋转z轴").min(-5).max(5).step(0.1);
boxFolder
  .addColor({ color: 0x00ff00 }, "color")
  .name("修改颜色")
  .onChange((e) => {
    box.material.color = new THREE.Color(e);
  });

const params = {
  visible: true,
  moveAnimation: () => {
    gsap.to(box.position, { x: 5, duration: 2 });
  },
  cameraAnimation: () => {
    gsap.to(camera.position, {
      duration: 1,
      x: 0,
      y: 0,
      z: -10,
    });
  },
};

boxFolder
  .add(params, "visible")
  .name("是否可见")
  .onChange((e) => {
    box.visible = e;
  });
boxFolder.add(params, "moveAnimation").name("移动动画");
boxFolder.open();

const cameraFolder = gui.addFolder("相机属性");
cameraFolder
  .add(camera.position, "x")
  .name("相机x轴")
  .min(-30)
  .max(30)
  .step(0.1);
cameraFolder
  .add(camera.position, "y")
  .name("相机y轴")
  .min(-30)
  .max(30)
  .step(0.1);
cameraFolder
  .add(camera.position, "z")
  .name("相机z轴")
  .min(-30)
  .max(30)
  .step(0.1);
cameraFolder
  .add(camera.rotation, "x")
  .name("相机旋转x轴")
  .min(-5)
  .max(5)
  .step(0.1);
cameraFolder
  .add(camera.rotation, "y")
  .name("相机旋转y轴")
  .min(-5)
  .max(5)
  .step(0.1);
cameraFolder
  .add(camera.rotation, "z")
  .name("相机旋转z轴")
  .min(-5)
  .max(5)
  .step(0.1);

cameraFolder.add(params, "cameraAnimation").name("相机移动位置");

cameraFolder.open();

// 轨道控制器对象
let controls: OrbitControls;
// 坐标辅助器
const axesHelper = new THREE.AxesHelper(20);
scene.add(axesHelper);

// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器大小
renderer.setSize(window.innerWidth, window.innerHeight);

const container = ref<HTMLElement | null>(null);

const render = () => {
  // box.position.x += 0.01;
  // box.rotation.x += 0.01;
  // if(box.position.x > 5) {
  //   box.position.x = 0;
  //   box.rotation.x = 0;
  // }
  renderer.render(scene, camera);
  requestAnimationFrame(render);
};

onMounted(() => {
  if (container.value) {
    // 添加轨道控制器
    // controls = new OrbitControls(camera, renderer.domElement);
    // controls.enableDamping = true;
    // controls.update();

    container.value.appendChild(renderer.domElement);
    render();

    let isMouseDown = false;
    container.value.addEventListener(
      "mousedown",
      () => {
        isMouseDown = true;
      },
      false
    );
    container.value.addEventListener(
      "mouseup",
      () => {
        isMouseDown = false;
      },
      false
    );
    container.value.addEventListener(
      "mouseout",
      () => {
        isMouseDown = false;
      },
      false
    );

    container.value.addEventListener("mousemove", (event) => {
      if (isMouseDown) {
        camera.rotation.x += event.movementY * 0.01;
        camera.rotation.y += event.movementX * 0.01;
        camera.rotation.order = "YXZ";
      }
    });
  }
});
</script>

<template>
  <div ref="container" class="container"></div>
</template>

<style lang="scss">
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
.container {
  width: 100vw;
  height: 100vh;
}
</style>
